home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / a_utils / _archvrs / unix / lha101u.lha / lha / src / lharc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-23  |  20.8 KB  |  961 lines

  1. /*----------------------------------------------------------------------*/
  2. /*        LHarc Archiver Driver for UNIX                */
  3. /*        This is part of LHarc UNIX Archiver Driver        */
  4. /*                                    */
  5. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  6. /*        Thanks to H.Yoshizaki. (MS-DOS LHarc)            */
  7. /*                                    */
  8. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  9. /*  V0.01  Alpha Version (for 4.2BSD)        1989.05.28  Y.Tagawa    */
  10. /*  V0.02  Alpha Version Rel.2            1989.05.29  Y.Tagawa    */
  11. /*  V0.03  Release #3  Beta Version        1989.07.02  Y.Tagawa    */
  12. /*  V0.03a Debug                1989.07.03  Y.Tagawa    */
  13. /*  V0.03b Modified                1989.07.13  Y.Tagawa    */
  14. /*  V0.03c Debug (Thanks to void@rena.dit.junet)1989.08.09  Y.Tagawa    */
  15. /*  V0.03d Modified (quiet and verbose)        1989.09.14  Y.Tagawa    */
  16. /*  V1.00  Fixed                1989.09.22  Y.Tagawa    */
  17. /*  V1.01  Bug Fixed                1989.12.25  Y.Tagawa    */
  18. /*                                    */
  19. /*  DOS-Version Original LHx V C2.01         (C) H.Yohizaki        */
  20. /*                                    */
  21. /*  V2.00  UNIX Lharc + DOS LHx -> OSK LHx    1990.11.01  Momozou    */
  22. /*  V2.01  Minor Modified            1990.11.24  Momozou    */
  23. /*                                    */
  24. /*  V0.02  LHx for UNIX                1991.11.18  M.Oki    */
  25. /*  V0.03  LHa for UNIX                1991.12.17  M.Oki    */
  26. /*  V0.04  LHa for UNIX    beta version        1992.01.20  M.Oki    */
  27. /*  V1.00  LHa for UNIX    Fixed            1992.03.19  M.Oki    */
  28. /*  V1.01u LHa for UNIX    archive .lzh extension    1992.04.24  G.Roelofs    */
  29. /*    "     "   "   "   chmod/chown, suid    1992.05.02  T.Kloos    */
  30. /*    "     "   "   "   better extension fix    1992.06.27  J.P.Radley    */
  31. /*    "     "   "   "   chown(-1), =- bugfixes    1992.09.22  G.Roelofs    */
  32. /*----------------------------------------------------------------------*/
  33.  
  34. #include "lharc.h"
  35.  
  36. /*----------------------------------------------------------------------*/
  37. /*                PROGRAM                 */
  38. /*----------------------------------------------------------------------*/
  39.  
  40.  
  41. #define CMD_UNKNOWN    0
  42. #define CMD_EXTRACT    1
  43. #define CMD_ADD        2
  44. #define CMD_LIST    3
  45. #define CMD_DELETE    4
  46.  
  47. static int    cmd = CMD_UNKNOWN;
  48. char    **cmd_filev;
  49. int    cmd_filec;
  50.  
  51. char    *archive_name;
  52. char    expanded_archive_name[FILENAME_LENGTH];
  53. char    temporary_name[FILENAME_LENGTH];
  54. char    backup_archive_name[FILENAME_LENGTH];
  55. char    *progname;
  56.  
  57. /* static functions */
  58. static void sort_files();
  59.  
  60. /* options */
  61. boolean    quiet = FALSE;
  62. boolean    text_mode = FALSE;
  63. boolean    verbose = FALSE;
  64. boolean    noexec = FALSE;    /* debugging option */
  65. boolean    force = FALSE;
  66. boolean    prof = FALSE;
  67. int compress_method = 5;    /* deafult -lh5- */
  68. int header_level = HEADER_LEVEL1;
  69. #ifdef EUC
  70. boolean euc_mode = FALSE;
  71. #endif
  72.  
  73. /* view command flags */
  74. boolean    verbose_listing = FALSE;
  75.  
  76. /* extract command flags */
  77. boolean    output_to_stdout = FALSE;
  78.  
  79. /* append command flags */
  80. boolean    new_archive = FALSE;
  81. boolean    update_if_newer = FALSE;
  82. boolean    delete_after_append = FALSE;
  83. boolean    generic_format = FALSE;
  84.  
  85. boolean    remove_temporary_at_error = FALSE;
  86. boolean    recover_archive_when_interrupt = FALSE;
  87. boolean    remove_extracting_file_when_interrupt = FALSE;
  88. boolean get_filename_from_stdin = FALSE;
  89. boolean ignore_directory = FALSE;
  90. boolean verify_mode = FALSE;
  91.  
  92. char *extract_directory = NULL;
  93. char **xfilev;
  94. int  xfilec = 257;
  95.  
  96. /*----------------------------------------------------------------------*/
  97. /* NOTES :        Text File Format                */
  98. /*    GENERATOR        NewLine                    */
  99. /*    [generic]        0D 0A                    */
  100. /*    [MS-DOS]        0D 0A                    */
  101. /*    [OS9][MacOS]        0D                    */
  102. /*    [UNIX]            0A                    */
  103. /*----------------------------------------------------------------------*/
  104.  
  105.  
  106. static void
  107. print_tiny_usage_and_exit ()
  108. {
  109.   fprintf (stderr, "\
  110. LHarc    for UNIX  V 1.02  Copyright(C) 1989  Y.Tagawa\n\
  111. LHx      for MSDOS V C2.01 Copyright(C) 1990  H.Yoshizaki\n\
  112. LHx(arc) for OSK   V 2.01  Modified     1990  Momozou\n\
  113. LHa      for UNIX  V 1.00  Copyright(C) 1992  Masaru Oki\n\
  114. LHa      for UNIX  V 1.01u Tom Kloos, Jean-Pierre Radley, Greg Roelofs 1992\n\
  115. ");
  116.   fprintf(stderr, "\
  117. usage: %s [-]{axelvudmcp}[qvnfodizg012][w=<dir>] archive_file [file...]\n\
  118. commands:                           options:\n\
  119.  a   Add(or replace) to archive      q  quiet\n\
  120.  x,e EXtract from archive            v  verbose\n\
  121.  l,v List / Verbose List             n  not execute\n\
  122.  u   Update newer files to archive   f  force (over write at extract)\n\
  123.  d   Delete from archive             t  FILES are TEXT file\n\
  124.  m   Move to archive (means 'ad')    o  use LHarc compatible method (a/u)\n\
  125.  c   re-Construct new archive        w=<dir> specify extract directory (x/e)\n\
  126.  p   Print to STDOUT from archive    d  delete FILES after (a/u/c)\n\
  127.  t   Test file CRC in archive        i  ignore directory path (x/e)\n\
  128.                                      z  files not compress (a/u)\n\
  129.                                      g  [Generic] format (for compatibility)\n\
  130.                                      0/1/2 header level (a/u)\n\
  131. ", progname);
  132. #ifdef EUC
  133.   fprintf (stderr, "\
  134.                                      e  TEXT code convert from/to EUC\n\
  135. ");
  136. #endif
  137.   exit (1);
  138. }
  139.  
  140. void
  141. main (argc, argv)
  142.      int argc;
  143.      char *argv[];
  144. {
  145.   char *p , inpbuf[256];
  146.  
  147.   progname = argv[0];
  148.  
  149.   if (argc < 2)
  150.     print_tiny_usage_and_exit ();
  151.   if (argc < 3) {
  152.     cmd = CMD_LIST;
  153.     argv--;
  154.     argc++;
  155.     goto work;
  156.   }
  157.   if ( argv[1][0]=='-' ) argv[1]++;
  158.   /* commands */
  159.   switch ( argv[1][0] )
  160.     {
  161.     case 'x':
  162.     case 'e':
  163.       cmd = CMD_EXTRACT;
  164.       break;
  165.  
  166.     case 'p':
  167.       output_to_stdout = TRUE;
  168.       cmd = CMD_EXTRACT;
  169.       break;
  170.  
  171.     case 'c':
  172.       new_archive = TRUE;
  173.       cmd = CMD_ADD;
  174.       break;
  175.  
  176.     case 'a':
  177.       cmd = CMD_ADD;
  178.       break;
  179.  
  180.     case 'd':
  181.       cmd = CMD_DELETE;
  182.       break;
  183.  
  184.     case 'u':
  185.       update_if_newer = TRUE;
  186.       cmd = CMD_ADD;
  187.       break;
  188.  
  189.     case 'm':
  190.       delete_after_append = TRUE;
  191.       cmd = CMD_ADD;
  192.       break;
  193.  
  194.     case 'v':
  195.       verbose_listing = TRUE;
  196.       cmd = CMD_LIST;
  197.       break;
  198.  
  199.     case 'l':
  200.       cmd = CMD_LIST;
  201.       break;
  202.  
  203.     case 't':
  204.       cmd = CMD_EXTRACT;
  205.       verify_mode = TRUE;
  206.       break;
  207.  
  208.     default:
  209.       print_tiny_usage_and_exit ();
  210.     
  211.     }
  212.  
  213.   /* options */
  214.   p = &argv[1][1];
  215.   for (p = &argv[1][1]; *p; )
  216.     {
  217.       switch ( (*p++) )
  218.     {
  219.         case 'q':    quiet = TRUE; break;
  220.         case 'f':    force = TRUE; break;
  221.         case 'p':    prof = TRUE; break;
  222.         case 'v':    verbose = TRUE; break;
  223.         case 't':    text_mode = TRUE; break;
  224. #ifdef EUC
  225.         case 'e':    text_mode = TRUE; euc_mode = TRUE; break;
  226. #endif
  227.         case 'n':    noexec = TRUE; break;
  228.         case 'g':    generic_format = TRUE; header_level = 0; break;
  229.         case 'd':    delete_after_append = TRUE; break;
  230.         case 'o':    compress_method = 1; header_level = 0; break;
  231.         case 'z':    compress_method = 0; break;
  232.         case 'i':    ignore_directory = TRUE; break;
  233.         case 'w':    if ( *p=='=' ) p++;
  234.                     extract_directory=p;
  235.                     while (*p) p++;
  236.                     break;
  237.         case '0':    header_level = HEADER_LEVEL0; break;
  238.         case '1':    header_level = HEADER_LEVEL1; break;
  239.         case '2':    header_level = HEADER_LEVEL2; break;
  240.         default:
  241.           fprintf(stderr, "%s: Unknown option '%c'.\n", progname, p[-1]);
  242.           exit(1);
  243.         }
  244.     }
  245.  
  246. work:
  247.   /* archive file name */
  248.   archive_name = argv[2];
  249.  
  250.   if (!strcmp(archive_name, "-"))
  251.     {
  252.       if (!isatty(1) && cmd == CMD_ADD) quiet = TRUE;
  253.     }
  254.   else
  255.     {
  256.       if (argc == 3 && !isatty(0))
  257.     get_filename_from_stdin = TRUE;
  258.     }
  259.  
  260.   /* target file name */
  261.   if ( get_filename_from_stdin )
  262.   {
  263.       cmd_filec = 0;
  264.     if ( (xfilev = (char **)malloc(sizeof(char *) * xfilec)) == NULL)
  265.         fatal_error("Virtual memory exhausted\n");
  266.      while ( gets( inpbuf ) )
  267.      {
  268.         if ( cmd_filec >= xfilec )
  269.         {
  270.             xfilec += 256;
  271.             cmd_filev = (char **)realloc(xfilev,
  272.                           sizeof(char *) * xfilec);
  273.             if ( cmd_filev == NULL )
  274.                 fatal_error("Virtual memory exhausted\n");
  275.             xfilev = cmd_filev;
  276.         }                
  277.          if ( strlen( inpbuf )<1 ) continue;
  278.          if ( (xfilev[cmd_filec++]=(char *)strdup(inpbuf))==NULL )
  279.              fatal_error("Virtual memory exhausted\n");
  280.      }
  281.      xfilev[cmd_filec] = NULL;
  282.      cmd_filev = xfilev;
  283.   }
  284.   else
  285.   {
  286.     cmd_filec = argc - 3;
  287.     cmd_filev = argv + 3;
  288.   }
  289.   sort_files ();
  290.  
  291.   /* make crc table */
  292.   make_crctable();
  293.  
  294.   switch (cmd)
  295.     {
  296.     case CMD_EXTRACT:    cmd_extract ();    break;
  297.     case CMD_ADD:    cmd_add ();    break;
  298.     case CMD_LIST:    cmd_list ();    break;
  299.     case CMD_DELETE:    cmd_delete ();    break;
  300.     }
  301.  
  302. #ifdef USE_PROF
  303.   if (!prof)
  304.     exit (0);
  305. #endif
  306.  
  307.   exit (0);
  308. }
  309.  
  310. static void
  311. message_1 (title, subject, name)
  312.      char *title, *subject, *name;
  313. {
  314.   fprintf (stderr, "%s: %s%s ", progname, title, subject);
  315.   fflush (stderr);
  316.  
  317.   if (errno == 0)
  318.     fprintf (stderr, "%s\n", name);
  319.   else
  320.     perror (name);
  321. }
  322.  
  323. void
  324. message (subject, name)
  325.      char *subject, *name;
  326. {
  327.   message_1 ("", subject, name);
  328. }
  329.  
  330. void
  331. warning (subject, name)
  332.      char *subject, *name;
  333. {
  334.   message_1 ("Warning: ", subject, name);
  335. }
  336.  
  337. void
  338. error (subject, msg)
  339.      char *subject, *msg;
  340. {
  341.   message_1 ("Error: ", subject, msg);
  342. }
  343.  
  344. void
  345. fatal_error (msg)
  346.      char *msg;
  347. {
  348.   message_1 ("Fatal error:", "", msg);
  349.  
  350.   if (remove_temporary_at_error)
  351.     unlink (temporary_name);
  352.  
  353.   exit (1);
  354. }
  355.  
  356. char *writting_filename;
  357. char *reading_filename;
  358.  
  359. void
  360. write_error ()
  361. {
  362.   fatal_error (writting_filename);
  363. }
  364.  
  365. void
  366. read_error ()
  367. {
  368.   fatal_error (reading_filename);
  369. }
  370.  
  371. void
  372. interrupt (signo)
  373.      int signo;
  374. {
  375.   errno = 0;
  376.   message ("Interrupted\n", "");
  377.  
  378.   if ( temporary_fp ) fclose (temporary_fp);
  379.   unlink (temporary_name);
  380.   if (recover_archive_when_interrupt)
  381.     rename (backup_archive_name, archive_name);
  382.   if (remove_extracting_file_when_interrupt)
  383.     {
  384.       errno = 0;
  385.       message ("Removing", writting_filename);
  386.       unlink (writting_filename);
  387.     }
  388.   signal (SIGINT, SIG_DFL);
  389.   signal (SIGHUP, SIG_DFL);
  390.   kill (getpid (), signo);
  391. }
  392.  
  393.  
  394.  
  395. /*----------------------------------------------------------------------*/
  396. /*                                    */
  397. /*----------------------------------------------------------------------*/
  398.  
  399. static int
  400. sort_by_ascii (a, b)
  401.      char **a, **b;
  402. {
  403.   register char *p, *q;
  404.   register int c1, c2;
  405.  
  406.   p = *a, q = *b;
  407.   if (generic_format)
  408.     {
  409.       do
  410.     {
  411.       c1 = *(unsigned char*)p ++;
  412.       c2 = *(unsigned char*)q ++;
  413.       if (!c1 || !c2)
  414.         break;
  415.       if (islower (c1))
  416.         c1 = toupper (c1);
  417.       if (islower (c2))
  418.         c2 = toupper (c2);
  419.     }
  420.       while (c1 == c2) ;
  421.       return c1 - c2;
  422.     }
  423.   else
  424.     {
  425.       while (*p == *q && *p != '\0')
  426.     p ++, q ++;
  427.       return *(unsigned char*)p - *(unsigned char*)q;
  428.     }
  429. }
  430.  
  431. static void
  432. sort_files ()
  433. {
  434.   if (cmd_filec > 1)
  435.     qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
  436. }
  437.  
  438. char *xmalloc (size)
  439.      int size;
  440. {
  441.   char *p = (char *)malloc (size);
  442.   if (!p)
  443.     fatal_error ("Not enough memory");
  444.   return p;
  445. }
  446.  
  447. char *xrealloc (old, size)
  448.      char *old;
  449.      int size;
  450. {
  451.   char *p = (char *)realloc (old, size);
  452.   if (!p)
  453.     fatal_error ("Not enough memory");
  454.   return p;
  455. }
  456.  
  457. /*----------------------------------------------------------------------*/
  458. /*                STRING POOL                */
  459. /*----------------------------------------------------------------------*/
  460.  
  461. /*
  462.  * string pool :
  463.  *    +-------------+-------------+---     ---+-------------+----------+
  464.  *    | N A M E 1 \0| N A M E 2 \0|    ...    | N A M E n \0|             |
  465.  *    +-------------+-------------+---     ---+-------------+----------+
  466.  *    ^                              ^         ^
  467.  * buffer+0                        buffer+used  buffer+size
  468.  */
  469.  
  470. /*
  471.  * vector :
  472.  *    +---------------+---------------+-------------     -------------+
  473.  *    | pointer to    | pointer to    | pointer to   ...  pointer to    |
  474.  *    |  string pool    |  N A M E 1    |  N A M E 2   ...   N A M E n    |
  475.  *    +---------------+---------------+-------------     -------------+
  476.  *    ^        ^
  477.  *   malloc base      returned
  478.  */
  479.  
  480. void
  481. init_sp (sp)
  482.      struct string_pool *sp;
  483. {
  484.   sp->size = 1024 - 8;        /* any ( >=0 ) */
  485.   sp->used = 0;
  486.   sp->n = 0;
  487.   sp->buffer = (char*)xmalloc (sp->size * sizeof (char));
  488. }
  489.  
  490. void
  491. add_sp (sp, name, len)
  492.      struct string_pool *sp;
  493.      char *name;        /* stored '\0' at tail */
  494.      int len;            /* include '\0' */
  495. {
  496.   while (sp->used + len > sp->size)
  497.     {
  498.       sp->size *= 2;
  499.       sp->buffer = (char*) xrealloc (sp->buffer, sp->size * sizeof (char));
  500.     }
  501.   bcopy (name, sp->buffer + sp->used, len);
  502.   sp->used += len;
  503.   sp->n ++;
  504. }
  505.  
  506. void
  507. finish_sp (sp, v_count, v_vector)
  508.      register struct string_pool *sp;
  509.      int *v_count;
  510.      char ***v_vector;
  511. {
  512.   int i;
  513.   register char *p;
  514.   char **v;
  515.  
  516.   v = (char**) xmalloc ((sp->n + 1) * sizeof (char*));
  517.   *v++ = sp->buffer;
  518.   *v_vector = v;
  519.   *v_count = sp->n;
  520.   p = sp->buffer;
  521.   for (i = sp->n; i; i --)
  522.     {
  523.       *v++ = p;
  524.       if (i - 1)
  525.     p += strlen (p) + 1;
  526.     }
  527. }
  528.  
  529. void
  530. free_sp (vector)
  531.      char **vector;
  532. {
  533.   vector --;
  534.   free (*vector);        /* free string pool */
  535.   free (vector);
  536. }
  537.  
  538.  
  539. /*----------------------------------------------------------------------*/
  540. /*            READ DIRECTORY FILES                */
  541. /*----------------------------------------------------------------------*/
  542.  
  543. static boolean
  544. include_path_p (path, name)
  545.      char *path, *name;
  546. {
  547.   char *n = name;
  548.   while (*path)
  549.     if (*path++ != *n++)
  550.       return (path[-1] == '/' && *n == '\0');
  551.   return (*n == '/' || (n != name && path[-1] == '/' && n[-1] == '/'));
  552. }
  553.  
  554. #define STREQU(a,b)    (((a)[0] == (b)[0]) ? (strcmp ((a),(b)) == 0) : FALSE)
  555. void
  556. cleaning_files (v_filec, v_filev)
  557.      int *v_filec;
  558.      char ***v_filev;
  559. {
  560.   char *flags;
  561.   struct stat stbuf;
  562.   register char **filev = *v_filev;
  563.   register int filec = *v_filec;
  564.   register char *p;
  565.   register int i, j;
  566.  
  567.   if (filec == 0)
  568.     return;
  569.  
  570.   flags = xmalloc (filec * sizeof (char));
  571.  
  572.   /* flags & 0x01 :    1: ignore */
  573.   /* flags & 0x02 :    1: directory, 0 : regular file */
  574.   /* flags & 0x04 :    1: need delete */
  575.  
  576.   for (i = 0; i < filec; i ++)
  577.     if (stat (filev[i], &stbuf) < 0)
  578.       {
  579.     flags[i] = 0x04;
  580.     fprintf (stderr,
  581.          "%s: Cannot access \"%s\", ignored.\n", progname, filev[i]);
  582.       }
  583.     else
  584.       {
  585.     if (is_regularfile (&stbuf))
  586.       flags[i] = 0x00;
  587.     else if (is_directory (&stbuf))
  588.       flags[i] = 0x02;
  589.     else
  590.       {
  591.         flags[i] = 0x04;
  592.         fprintf (stderr,
  593.              "%s: Cannot archive \"%s\", ignored.\n", progname, filev[i]);
  594.       }
  595.       }
  596.   errno = 0;
  597.  
  598.   for (i = 0; i < filec; i ++)
  599.     {
  600.       p = filev[i];
  601.       if ((flags[i] & 0x07) == 0x00)
  602.     {            /* regular file, not deleted/ignored */
  603.       for (j = i + 1; j < filec; j ++)
  604.         {
  605.           if ((flags[j] & 0x07) == 0x00)
  606.         {        /* regular file, not deleted/ignored */
  607.           if (STREQU (p, filev[j]))
  608.             flags[j] = 0x04; /* delete */
  609.         }
  610.         }
  611.     }
  612.       else if ((flags[i] & 0x07) == 0x02)
  613.     {            /* directory, not deleted/ignored */
  614.       for (j = i + 1; j < filec; j ++)
  615.         {
  616.           if ((flags[j] & 0x07) == 0x00)
  617.         {        /* regular file, not deleted/ignored */
  618.           if (include_path_p (p, filev[j]))
  619.             flags[j] = 0x04; /* delete */
  620.         }
  621.           else if ((flags[j] & 0x07) == 0x02)
  622.         {        /* directory, not deleted/ignored */
  623.           if (include_path_p (p, filev[j]))
  624.             flags[j] = 0x04; /* delete */
  625.         }
  626.         }
  627.     }
  628.     }
  629.  
  630.   for (i = j = 0; i < filec; i ++)
  631.     {
  632.       if ((flags[i] & 0x04) == 0)
  633.     {
  634.       if (i != j)
  635.         filev[j] = filev[i];
  636.       j ++;
  637.     }
  638.     }
  639.   *v_filec = j;
  640.  
  641.   free (flags);
  642. }
  643.  
  644. #ifdef NODIRECTORY
  645. /* please need your imprementation */
  646. boolean
  647. find_files (name, v_filec, v_filev)
  648.      char *name;
  649.      int *v_filec;
  650.      char ***v_filev;
  651. {
  652.   return FALSE;            /* DUMMY */
  653. }
  654.  
  655. void
  656. free_files (filec, filev)
  657.      int filec;
  658.      char **filev;
  659. {
  660.   /* do nothing */
  661. }
  662. #else
  663. boolean
  664. find_files (name, v_filec, v_filev)
  665.      char *name;
  666.      int *v_filec;
  667.      char ***v_filev;
  668. {
  669.   struct string_pool sp;
  670.   char newname[FILENAME_LENGTH];
  671.   int len, n;
  672.   DIR *dirp;
  673.   DIRENTRY *dp;
  674.   struct stat tmp_stbuf, arc_stbuf, fil_stbuf;
  675.  
  676.   strcpy (newname, name);
  677.   len = strlen (name);
  678.   if (len > 0 && newname[len-1] != '/')
  679.     newname[len++] = '/';
  680.  
  681.   dirp = opendir (name);
  682.   if (!dirp)
  683.     return FALSE;
  684.  
  685.   init_sp (&sp);
  686.  
  687.   GETSTAT(temporary_name, &tmp_stbuf);
  688.   GETSTAT(archive_name, &arc_stbuf);
  689.  
  690.   for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
  691.     {
  692.       n = NAMLEN (dp);
  693.       strncpy (newname+len, dp->d_name, n);
  694.       newname[len + n] = '\0';
  695.       if (GETSTAT(newname, &fil_stbuf) < 0) continue;
  696.       if ((dp->d_ino != 0) &&
  697.       /* exclude '.' and '..' */
  698.       ((dp->d_name[0] != '.') ||
  699.        ((n != 1) &&
  700.         ((dp->d_name[1] != '.') ||
  701.          (n != 2)))) &&
  702.       ((tmp_stbuf.st_dev != fil_stbuf.st_dev ||
  703.         tmp_stbuf.st_ino != fil_stbuf.st_ino) &&
  704.        (arc_stbuf.st_dev != fil_stbuf.st_dev ||
  705.         arc_stbuf.st_ino != fil_stbuf.st_ino)))
  706.  
  707.     {
  708.       add_sp (&sp, newname, len + n + 1);
  709.     }
  710.     }
  711.   closedir (dirp);
  712.   finish_sp (&sp, v_filec, v_filev);
  713.   if (*v_filec > 1)
  714.     qsort (*v_filev, *v_filec, sizeof (char*), sort_by_ascii);
  715.   cleaning_files (v_filec, v_filev);
  716.  
  717.   return TRUE;
  718. }
  719.  
  720. void
  721. free_files (filec, filev)
  722.      int filec;
  723.      char **filev;
  724. {
  725.   free_sp (filev);
  726. }
  727. #endif
  728.  
  729. /*----------------------------------------------------------------------*/
  730. /*                                    */
  731. /*----------------------------------------------------------------------*/
  732.  
  733. /* Build temporary file name and store to TEMPORARY_NAME */
  734. void
  735. build_temporary_name ()
  736. {
  737. #ifdef TMP_FILENAME_TEMPLATE
  738.   /* "/tmp/lhXXXXXX" etc. */
  739.   strcpy (temporary_name, TMP_FILENAME_TEMPLATE);
  740.   mktemp (temporary_name);
  741. #else
  742.   char *p, *s;
  743.  
  744.   strcpy (temporary_name, archive_name);
  745.   for (p = temporary_name, s = (char*)0; *p; p ++)
  746.     if (*p == '/')
  747.       s = p;
  748.   strcpy ((s ? s+1 : temporary_name), "lhXXXXXX");
  749.   mktemp (temporary_name);
  750. #endif
  751. }
  752.  
  753. static void
  754. modify_filename_extention (buffer, ext)
  755.      char *buffer;
  756.      char *ext;
  757. {
  758.   register char *p, *dot;
  759.  
  760.   for (p = buffer, dot = (char*)0; *p; p ++)
  761.     {
  762.       if (*p == '.')
  763.         dot = p;
  764.       else if (*p == '/')
  765.         dot = (char*)0;
  766.     }
  767.  
  768.   if (dot)
  769.     p = dot;
  770.  
  771.   strcpy (p, ext);
  772. }
  773.  
  774. /* build backup file name */
  775. void
  776. build_backup_name (buffer, original)
  777.      char *buffer;
  778.      char *original;
  779. {
  780.   strcpy (buffer, original);
  781.   modify_filename_extention (buffer, BACKUPNAME_EXTENTION); /* ".bak" */
  782. }
  783.  
  784. void
  785. build_standard_archive_name (buffer, orginal)
  786.      char *buffer;
  787.      char *orginal;
  788. {
  789.   strcpy (buffer, orginal);
  790.   modify_filename_extention (buffer, ARCHIVENAME_EXTENTION); /* ".lzh" */
  791. }
  792.  
  793. /*----------------------------------------------------------------------*/
  794. /*                                    */
  795. /*----------------------------------------------------------------------*/
  796.  
  797. extern int patmatch();
  798.  
  799. boolean
  800. need_file (name)
  801.      char *name;
  802. {
  803.   int i;
  804.  
  805.   if (cmd_filec == 0)
  806.     return TRUE;
  807.  
  808.   for (i = 0; i < cmd_filec; i ++)
  809.     {
  810.       if (patmatch(cmd_filev[i], name, 0 ) )
  811.         return TRUE;
  812.     }
  813.  
  814.   return FALSE;
  815. }
  816.  
  817. FILE *
  818. xfopen (name, mode)
  819.      char *name, *mode;
  820. {
  821.   FILE *fp;
  822.  
  823.   if ((fp = fopen (name, mode)) == NULL)
  824.     fatal_error (name);
  825.  
  826.   return fp;
  827. }
  828.  
  829.  
  830. /*----------------------------------------------------------------------*/
  831. /*                                    */
  832. /*----------------------------------------------------------------------*/
  833. int    archive_file_mode;
  834. int    archive_file_gid;
  835.  
  836. static boolean
  837. open_old_archive_1 (name, v_fp)
  838.      char *name;
  839.      FILE **v_fp;
  840. {
  841.   FILE *fp;
  842.   struct stat stbuf;
  843.  
  844.   if (stat (name, &stbuf) >= 0 &&
  845.       is_regularfile (&stbuf) &&
  846.       (fp = fopen (name, READ_BINARY)) != NULL)
  847.     {
  848.       *v_fp = fp;
  849.       archive_file_gid = stbuf.st_gid;
  850.       archive_file_mode = stbuf.st_mode;
  851.       return TRUE;
  852.     }
  853.  
  854.   *v_fp = NULL;
  855.   archive_file_gid = -1;
  856.   return FALSE;
  857. }
  858.  
  859. FILE *
  860. open_old_archive ()
  861. {
  862.   FILE *fp;
  863.   char *p;
  864.  
  865.   if (!strcmp(archive_name, "-"))
  866.     {
  867.       if (cmd == CMD_EXTRACT || cmd == CMD_LIST) return stdin;
  868.       else return NULL;
  869.     }
  870. #ifndef USG
  871.   if (p = (char *)rindex(archive_name,'.'))
  872.     {
  873.       if ( strucmp(".LZH",p)==0
  874.           || strucmp(".LZS",p)==0
  875.           || strucmp(".COM",p)==0        /* DOS SFX */
  876.           || strucmp(".EXE",p)==0
  877.             || strucmp(".X"  ,p)==0        /* HUMAN SFX */
  878.           || strucmp(".BAK",p)==0 )    /* for BackUp */
  879.       {
  880.         open_old_archive_1 (archive_name, &fp );
  881.         return fp;
  882.       }
  883.     }
  884. #endif
  885.  
  886.   if ( open_old_archive_1 (archive_name, &fp) )
  887.         return fp;
  888.   sprintf( expanded_archive_name , "%s.lzh",archive_name);
  889.   if ( open_old_archive_1 (expanded_archive_name, &fp) )
  890.   {
  891.     archive_name = expanded_archive_name;
  892.     return fp;
  893.   }
  894. /*  if ( (errno&0xffff)!=E_PNNF )
  895.   {
  896.       archive_name = expanded_archive_name;
  897.       return NULL;
  898.   }
  899. */
  900.   sprintf( expanded_archive_name, "%s.lzs",archive_name);
  901.   if ( open_old_archive_1 (expanded_archive_name, &fp ) )
  902.   {
  903.       archive_name = expanded_archive_name;
  904.     return fp;
  905.   }
  906. /*  if ( (errno&0xffff)!=E_PNNF )
  907.   {
  908.       archive_name = expanded_archive_name;
  909.     return NULL;
  910.   }
  911. */
  912.   sprintf( expanded_archive_name , "%s.lzh",archive_name);
  913.   archive_name = expanded_archive_name;
  914.   return NULL;
  915. }
  916.  
  917. int
  918. inquire (msg, name, selective)
  919.      char *msg, *name, *selective;
  920. {
  921.   char buffer[1024];
  922.   char *p;
  923.  
  924.   for (;;)
  925.     {
  926.       fprintf (stderr, "%s %s ", name, msg);
  927.       fflush (stderr);
  928.  
  929.       fgets (buffer, 1024, stdin);
  930.  
  931.       for (p = selective; *p; p++)
  932.     if (buffer[0] == *p)
  933.       return p - selective;
  934.     }
  935.   /*NOTREACHED*/
  936. }
  937.  
  938. void
  939. write_archive_tail (nafp)
  940.      FILE *nafp;
  941. {
  942.   putc (0x00, nafp);
  943. }
  944.  
  945. void
  946. copy_old_one (oafp, nafp, hdr)
  947.      FILE *oafp, *nafp;
  948.      LzHeader *hdr;
  949. {
  950.   if (noexec)
  951.     {
  952.       fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
  953.     }
  954.   else
  955.     {
  956.       reading_filename = archive_name;
  957.       writting_filename = temporary_name;
  958.       copyfile (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size,0);
  959.     }
  960. }
  961.